package com.smart.community.property.service.impl;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.property.entity.RepairProgress;
import com.smart.community.property.mapper.RepairProgressMapper;
import com.smart.community.property.service.IRepairProgressService;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 维修工单进度记录服务实现类
 * 
 * 严格按照《Java后端SpringBoot代码开发规范.md》Service层生产环境标准实现：
 * - 生产环境标准：移除throws Exception声明，使用优雅降级处理
 * - 缓存策略：实现Redis缓存机制，提高查询性能
 * - 性能优化：添加性能监控和统计功能
 * - 异常处理：统一异常处理机制，确保系统稳定性
 * - 参数验证：完善的参数验证和业务逻辑校验
 * - 工具方法：实现业务统计和用户信息获取工具方法
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 3.0.0 - 生产环境标准优化版本
 */
@Slf4j
@Service
public class RepairProgressServiceImpl extends ServiceImpl<RepairProgressMapper, RepairProgress> implements IRepairProgressService {

    @Autowired
    private RepairProgressMapper repairProgressMapper;

    @Override
    @GlobalTransactional
    @CacheEvict(value = "repairProgress", key = "'order:' + #progress.orderId", condition = "#progress != null")
    public boolean saveProgress(RepairProgress progress) {
        long startTime = System.currentTimeMillis();
        log.info("保存进度记录开始，工单ID：{}", progress != null ? progress.getOrderId() : "null");
        
        try {
            // 参数校验
            if (progress == null) {
                log.warn("保存进度记录失败：进度记录对象为空");
                return false;
            }

            // 设置默认值
            if (progress.getStatus() == null) {
                progress.setStatus(SystemStatusEnum.ENABLED.getCode());
            }
            if (progress.getCreateTime() == null) {
                progress.setCreateTime(LocalDateTime.now());
            }
            if (progress.getProgressTime() == null) {
                progress.setProgressTime(LocalDateTime.now());
            }

            // 自动设置排序字段
            if (progress.getSortOrder() == null) {
                int nextOrder = getNextSortOrder(progress.getOrderId());
                progress.setSortOrder(nextOrder);
            }

            int result = repairProgressMapper.insertProgress(progress);
            if (result > 0) {
                long responseTime = System.currentTimeMillis() - startTime;
                log.info("保存进度记录成功，工单ID: {}, 进度类型: {}, 进度ID: {}, 耗时：{}ms", 
                        progress.getOrderId(), progress.getProgressType(), progress.getId(), responseTime);
                return true;
            } else {
                long responseTime = System.currentTimeMillis() - startTime;
                log.warn("保存进度记录失败，工单ID: {}, 进度类型: {}, 耗时：{}ms", 
                        progress.getOrderId(), progress.getProgressType(), responseTime);
                return false;
            }
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("保存进度记录异常，工单ID: {}, 耗时：{}ms", 
                    progress != null ? progress.getOrderId() : "null", responseTime, e);
            return false; // 生产环境标准：返回false而不是抛出异常
        }
    }

    @Override
    @GlobalTransactional
    public boolean createProgress(Long orderId, String orderNo, Integer progressType, String progressTitle,
                                 String progressContent, Long operatorId, String operatorName) throws Exception {
        long startTime = System.currentTimeMillis();
        log.info("创建进度记录开始，工单ID：{}，进度类型：{}", orderId, progressType);
        
        try {
            // 参数校验
            if (orderId == null || !StringUtils.hasText(orderNo) || progressType == null) {
                log.warn("创建进度记录参数不完整，工单ID: {}, 工单号: {}, 进度类型: {}", orderId, orderNo, progressType);
                return false;
            }

            boolean result = createProgressWithRepairman(orderId, orderNo, progressType, progressTitle, progressContent,
                    operatorId, operatorName, null, null, LocalDateTime.now());
            
            long responseTime = System.currentTimeMillis() - startTime;
            if (result) {
                log.info("创建进度记录成功，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime);
            } else {
                log.warn("创建进度记录失败，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime);
            }
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("创建进度记录异常，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime, e);
            throw e; // 根据智慧社区微服务架构总览要求，此方法需要抛出异常
        }
    }

    @Override
    @GlobalTransactional
    public boolean createProgressWithRepairman(Long orderId, String orderNo, Integer progressType, String progressTitle,
                                              String progressContent, Long operatorId, String operatorName,
                                              Long repairmanId, String repairmanName, LocalDateTime progressTime) throws Exception {
        long startTime = System.currentTimeMillis();
        log.info("创建进度记录（含维修人员）开始，工单ID：{}，进度类型：{}", orderId, progressType);
        
        try {
            // 参数校验
            if (orderId == null || !StringUtils.hasText(orderNo) || progressType == null) {
                log.warn("创建进度记录参数不完整，工单ID: {}, 工单号: {}, 进度类型: {}", orderId, orderNo, progressType);
                return false;
            }

            RepairProgress progress = new RepairProgress();
            progress.setOrderId(orderId);
            progress.setOrderNo(orderNo);
            progress.setProgressType(progressType);
            progress.setProgressTitle(progressTitle);
            progress.setProgressContent(progressContent);
            progress.setProgressTime(progressTime != null ? progressTime : LocalDateTime.now());
            progress.setOperatorId(operatorId);
            progress.setOperatorName(operatorName);
            progress.setRepairmanId(repairmanId);
            progress.setRepairmanName(repairmanName);

            boolean result = saveProgress(progress);
            
            long responseTime = System.currentTimeMillis() - startTime;
            if (result) {
                log.info("创建进度记录（含维修人员）成功，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime);
            } else {
                log.warn("创建进度记录（含维修人员）失败，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime);
            }
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("创建进度记录（含维修人员）异常，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime, e);
            throw e; // 根据智慧社区微服务架构总览要求，此方法需要抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'order:' + #orderId", unless = "#result == null || #result.isEmpty()")
    public List<RepairProgress> getProgressListByOrderId(Long orderId) {
        long startTime = System.currentTimeMillis();
        log.info("查询工单进度记录，工单ID：{}", orderId);
        
        try {
            if (orderId == null) {
                log.warn("查询工单进度记录失败：工单ID为空");
                return Collections.emptyList();
            }
            
            List<RepairProgress> result = repairProgressMapper.selectByOrderId(orderId);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("查询工单进度记录成功，工单ID: {}, 记录数量: {}, 耗时：{}ms", orderId, result.size(), responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("查询工单进度记录异常，工单ID: {}, 耗时：{}ms", orderId, responseTime, e);
            return Collections.emptyList(); // 生产环境标准：返回空列表而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'orderNo:' + #orderNo", unless = "#result == null || #result.isEmpty()")
    public List<RepairProgress> getProgressListByOrderNo(String orderNo) {
        long startTime = System.currentTimeMillis();
        log.info("查询工单进度记录，工单号：{}", orderNo);
        
        try {
            if (!StringUtils.hasText(orderNo)) {
                log.warn("查询工单进度记录失败：工单号为空");
                return Collections.emptyList();
            }
            
            List<RepairProgress> result = repairProgressMapper.selectByOrderNo(orderNo);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("查询工单进度记录成功，工单号: {}, 记录数量: {}, 耗时：{}ms", orderNo, result.size(), responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("查询工单进度记录异常，工单号: {}, 耗时：{}ms", orderNo, responseTime, e);
            return Collections.emptyList(); // 生产环境标准：返回空列表而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'latest:' + #orderId", unless = "#result == null")
    public RepairProgress getLatestProgressByOrderId(Long orderId) {
        long startTime = System.currentTimeMillis();
        log.info("查询工单最新进度记录，工单ID：{}", orderId);
        
        try {
            if (orderId == null) {
                log.warn("查询工单最新进度记录失败：工单ID为空");
                return null;
            }
            
            RepairProgress result = repairProgressMapper.selectLatestByOrderId(orderId);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("查询工单最新进度记录成功，工单ID: {}, 进度ID: {}, 耗时：{}ms", 
                    orderId, result != null ? result.getId() : "null", responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("查询工单最新进度记录异常，工单ID: {}, 耗时：{}ms", orderId, responseTime, e);
            return null; // 生产环境标准：返回null而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'orderType:' + #orderId + ':' + #progressType", unless = "#result == null")
    public RepairProgress getProgressByOrderIdAndType(Long orderId, Integer progressType) {
        long startTime = System.currentTimeMillis();
        log.info("查询工单指定类型进度记录，工单ID：{}，进度类型：{}", orderId, progressType);
        
        try {
            if (orderId == null || progressType == null) {
                log.warn("查询工单指定类型进度记录失败：工单ID或进度类型为空，工单ID: {}, 进度类型: {}", orderId, progressType);
                return null;
            }
            
            RepairProgress result = repairProgressMapper.selectByOrderIdAndType(orderId, progressType);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("查询工单指定类型进度记录成功，工单ID: {}, 进度类型: {}, 进度ID: {}, 耗时：{}ms", 
                    orderId, progressType, result != null ? result.getId() : "null", responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("查询工单指定类型进度记录异常，工单ID: {}, 进度类型: {}, 耗时：{}ms", orderId, progressType, responseTime, e);
            return null; // 生产环境标准：返回null而不是抛出异常
        }
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = "repairProgress", key = "'order:' + #orderId", condition = "#orderId != null")
    public boolean deleteProgressByOrderId(Long orderId) {
        long startTime = System.currentTimeMillis();
        log.info("删除工单进度记录，工单ID：{}", orderId);
        
        try {
            if (orderId == null) {
                log.warn("删除工单进度记录失败：工单ID为空");
                return false;
            }
            
            int result = repairProgressMapper.deleteByOrderId(orderId);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("删除工单进度记录成功，工单ID: {}, 删除数量: {}, 耗时：{}ms", orderId, result, responseTime);
            return result > 0;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("删除工单进度记录异常，工单ID: {}, 耗时：{}ms", orderId, responseTime, e);
            return false; // 生产环境标准：返回false而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'count:' + #orderId", unless = "#result == 0")
    public int countProgressByOrderId(Long orderId) {
        long startTime = System.currentTimeMillis();
        log.info("统计工单进度记录数量，工单ID：{}", orderId);
        
        try {
            if (orderId == null) {
                log.warn("统计工单进度记录数量失败：工单ID为空");
                return 0;
            }
            
            int result = repairProgressMapper.countByOrderId(orderId);
            long responseTime = System.currentTimeMillis() - startTime;
            log.info("统计工单进度记录数量成功，工单ID: {}, 数量: {}, 耗时：{}ms", orderId, result, responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("统计工单进度记录数量异常，工单ID: {}, 耗时：{}ms", orderId, responseTime, e);
            return 0; // 生产环境标准：返回0而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'timeRange:' + #startTime + ':' + #endTime", unless = "#result == null || #result.isEmpty()")
    public List<RepairProgress> getProgressListByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        long startTimeMs = System.currentTimeMillis();
        log.info("查询时间范围内进度记录，开始时间：{}，结束时间：{}", startTime, endTime);
        
        try {
            if (startTime == null || endTime == null) {
                log.warn("查询时间范围内进度记录失败：开始时间或结束时间为空，开始时间: {}, 结束时间: {}", startTime, endTime);
                return Collections.emptyList();
            }
            
            List<RepairProgress> result = repairProgressMapper.selectByTimeRange(startTime, endTime);
            long responseTime = System.currentTimeMillis() - startTimeMs;
            log.info("查询时间范围内进度记录成功，开始时间: {}, 结束时间: {}, 记录数量: {}, 耗时：{}ms", 
                    startTime, endTime, result.size(), responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTimeMs;
            log.error("查询时间范围内进度记录异常，开始时间: {}, 结束时间: {}, 耗时：{}ms", startTime, endTime, responseTime, e);
            return Collections.emptyList(); // 生产环境标准：返回空列表而不是抛出异常
        }
    }

    @Override
    @Cacheable(value = "repairProgress", key = "'repairman:' + #repairmanId + ':' + #startTime + ':' + #endTime", unless = "#result == null || #result.isEmpty()")
    public List<RepairProgress> getProgressListByRepairmanId(Long repairmanId, LocalDateTime startTime, LocalDateTime endTime) {
        long startTimeMs = System.currentTimeMillis();
        log.info("查询维修人员进度记录，维修人员ID：{}，开始时间：{}，结束时间：{}", repairmanId, startTime, endTime);
        
        try {
            if (repairmanId == null) {
                log.warn("查询维修人员进度记录失败：维修人员ID为空");
                return Collections.emptyList();
            }
            if (startTime == null || endTime == null) {
                log.warn("查询维修人员进度记录失败：开始时间或结束时间为空，维修人员ID: {}, 开始时间: {}, 结束时间: {}",
                        repairmanId, startTime, endTime);
                return Collections.emptyList();
            }
            
            List<RepairProgress> result = repairProgressMapper.selectByRepairmanId(repairmanId, startTime, endTime);
            long responseTime = System.currentTimeMillis() - startTimeMs;
            log.info("查询维修人员进度记录成功，维修人员ID: {}, 开始时间: {}, 结束时间: {}, 记录数量: {}, 耗时：{}ms",
                    repairmanId, startTime, endTime, result.size(), responseTime);
            return result;
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTimeMs;
            log.error("查询维修人员进度记录异常，维修人员ID: {}, 耗时：{}ms", repairmanId, responseTime, e);
            return Collections.emptyList(); // 生产环境标准：返回空列表而不是抛出异常
        }
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = "repairProgress", allEntries = true, condition = "#progressList != null && !#progressList.isEmpty()")
    public boolean batchCreateProgress(List<RepairProgress> progressList) {
        long startTime = System.currentTimeMillis();
        log.info("批量创建进度记录开始，数量：{}", progressList != null ? progressList.size() : 0);
        
        try {
            if (progressList == null || progressList.isEmpty()) {
                log.warn("批量创建进度记录失败：进度记录列表为空");
                return false;
            }

            // 为每个进度记录设置默认值
            for (RepairProgress progress : progressList) {
                if (progress.getStatus() == null) {
                    progress.setStatus(SystemStatusEnum.ENABLED.getCode());
                }
                if (progress.getCreateTime() == null) {
                    progress.setCreateTime(LocalDateTime.now());
                }
                if (progress.getProgressTime() == null) {
                    progress.setProgressTime(LocalDateTime.now());
                }
                if (progress.getSortOrder() == null) {
                    int nextOrder = getNextSortOrder(progress.getOrderId());
                    progress.setSortOrder(nextOrder);
                }
            }

            int result = repairProgressMapper.batchInsertProgress(progressList);
            long responseTime = System.currentTimeMillis() - startTime;
            if (result > 0) {
                log.info("批量创建进度记录成功，数量: {}, 耗时：{}ms", result, responseTime);
                return true;
            } else {
                log.warn("批量创建进度记录失败，预期数量: {}, 实际插入数量: {}, 耗时：{}ms", 
                        progressList.size(), result, responseTime);
                return false;
            }
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("批量创建进度记录异常，预期数量: {}, 耗时：{}ms", 
                    progressList != null ? progressList.size() : 0, responseTime, e);
            return false; // 生产环境标准：返回false而不是抛出异常
        }
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = "repairProgress", key = "'order:' + #orderId", condition = "#orderId != null")
    public boolean updateProgressContent(Long orderId, String progressContent) {
        long startTime = System.currentTimeMillis();
        log.info("更新进度记录内容，工单ID：{}", orderId);
        
        try {
            if (orderId == null || !StringUtils.hasText(progressContent)) {
                log.warn("更新进度记录内容参数不完整，工单ID: {}, 进度内容: {}", orderId, progressContent);
                return false;
            }

            // 获取最新的进度记录
            RepairProgress latestProgress = getLatestProgressByOrderId(orderId);
            if (latestProgress == null) {
                log.warn("未找到工单的最新进度记录，工单ID: {}", orderId);
                return false;
            }

            // 更新进度内容
            int result = repairProgressMapper.updateProgressContent(latestProgress.getId(), progressContent);
            long responseTime = System.currentTimeMillis() - startTime;
            if (result > 0) {
                log.info("更新进度记录内容成功，工单ID: {}, 进度ID: {}, 耗时：{}ms", orderId, latestProgress.getId(), responseTime);
                return true;
            } else {
                log.warn("更新进度记录内容失败，工单ID: {}, 进度ID: {}, 耗时：{}ms", orderId, latestProgress.getId(), responseTime);
                return false;
            }
        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("更新进度记录内容异常，工单ID: {}, 耗时：{}ms", orderId, responseTime, e);
            return false; // 生产环境标准：返回false而不是抛出异常
        }
    }

    /**
     * 获取下一个排序序号
     * 
     * @param orderId 工单ID
     * @return 下一个排序序号
     */
    private int getNextSortOrder(Long orderId) {
        try {
            if (orderId == null) {
                log.warn("获取下一个排序序号失败：工单ID为空");
                return 1;
            }
            int count = countProgressByOrderId(orderId);
            int nextOrder = count + 1;
            log.debug("获取下一个排序序号成功，工单ID: {}, 当前数量: {}, 下一个序号: {}", orderId, count, nextOrder);
            return nextOrder;
        } catch (Exception e) {
            log.warn("获取下一个排序序号失败，使用默认值1，工单ID: {}", orderId, e);
            return 1;
        }
    }

} 
